import * as d3 from 'd3'
import aiw from '@/aiw-agent';
import { reactive } from 'vue';

export const store = reactive({
    theme: 'light',
    focusedNode: null
})

// 常量配置
export const CONFIG = {
  NODE_RADIUS: 20,
  LINK_DISTANCE: 150,
  CHARGE_STRENGTH: -300,
  ZOOM_SCALE_EXTENT: [0.2, 4],
  TRANSITION_DURATION: 600,
  ALPHA_MIN: 0.01,
  ALPHA_DECAY: 0.1,
  NODE_LOCK_DURATION: 1000,
  EDGE_BUFFER: 100
}

export class GalaxyCore {
  constructor() {
    // 状态管理
    this.store = store;
    this.state = {
      width: 0,
      height: 0,
    }
    
    // 数据相关
    this.clusterCounter = 0
    this.colorGroupCounter = 0
    this.colorScale = d3.scaleOrdinal(d3.schemeTableau10)
    this.root = this.createRootNode()
    
    // D3相关变量
    this.svgElement = null
    this.simulation = null
    this.zoom = null
    this.transformState = null
    this.nodeEls = null
    this.linkEls = null
    this.gContent = null
    this.gLinks = null
    this.gNodes = null

    this.d3 = d3;
    
    // 事件监听
    this.eventListeners = {}
  }
  
  // 创建根节点
  createRootNode() {
    return {
      id: '0',
      label: '奇点',
      exploded: false,
      loading: false,
      cluster: this.clusterCounter++,
      colorGroup: this.colorGroupCounter++,
      children: [],
      x: 0,
      y: 0
    }
  }
  
  // 初始化
  initialize(svgElement, width, height) {
    this.svgElement = svgElement
    this.state.width = width
    this.state.height = height
    this.root.x = width / 2
    this.root.y = height / 2
    
    this.initZoom()
    this.update()
  }
  
  // 初始化缩放
  initZoom() {
    this.zoom = d3.zoom()
      .scaleExtent(CONFIG.ZOOM_SCALE_EXTENT)
      .on('zoom', (event) => this.zoomed(event))
      
    d3.select(this.svgElement).call(this.zoom)
  }
  
  // 缩放处理
  zoomed(event) {
    this.transformState = event.transform || d3.zoomIdentity
    if (this.gContent) {
      this.gContent.attr('transform', this.transformState)
    }
    this.emit('zoom', this.transformState)
  }
  
  // 初始化力导向模拟
  initializeSimulation(nodes, links, centerNode = null) {
    this.simulation = d3.forceSimulation(nodes)
      .force('link', d3.forceLink(links).id(d => d.id).distance(CONFIG.LINK_DISTANCE).strength(1))
      .force('charge', d3.forceManyBody().strength(CONFIG.CHARGE_STRENGTH))
      .force('center', centerNode 
        ? d3.forceCenter(centerNode.x, centerNode.y).strength(0.1) 
        : d3.forceCenter(this.state.width / 2, this.state.height / 2)
      )
      .force('collide', d3.forceCollide(CONFIG.NODE_RADIUS * 1.5))
      .alphaMin(CONFIG.ALPHA_MIN)
      .alphaDecay(CONFIG.ALPHA_DECAY)
      .on('tick', () => this.ticked())
  }
  
  // 力导向更新
  ticked() {
    if (this.linkEls) {
      this.linkEls
        .attr('x1', d => d.source.x)
        .attr('y1', d => d.source.y)
        .attr('x2', d => d.target.x)
        .attr('y2', d => d.target.y)
    }

    if (this.nodeEls) {
      this.nodeEls.attr('transform', d => `translate(${d.x},${d.y})`)
    }
  }
  
  // 启用拖拽
  enableDrag(selection) {
    selection.call(
      d3.drag()
        .on('start', (event, d) => {
          if (!event.active) this.simulation.alphaTarget(0.3).restart()
          d.fx = d.x
          d.fy = d.y
        })
        .on('drag', (event, d) => {
          d.fx = event.x
          d.fy = event.y
        })
        .on('end', (event, d) => {
          if (!event.active) this.simulation.alphaTarget(0)
          d.fx = null
          d.fy = null
        })
    )
  }
  
  // 数据遍历
  traverse(node, callback) {
    callback(node)
    if (node.children) {
      node.children.forEach(child => this.traverse(child, callback))
    }
  }
  
  // 扁平化树结构
  flattenTree(rootNode) {
    const nodes = []
    const links = []

    this.traverse(rootNode, node => {
      nodes.push(node)
      if (node.children) {
        node.children.forEach(child => {
          links.push({ source: node.id, target: child.id })
        })
      }
    })

    return { nodes, links }
  }
  
  // 高亮聚焦节点
  highlightFocusedNode() {
    if (!this.nodeEls || !this.store.focusedNode) return

    this.nodeEls.select('circle')
      .style('stroke-width', d =>
        d.id === this.store.focusedNode.id ? (d.loading ? 3 : 1.5) : 1.5
      )
      .style('stroke', d =>
        d.id === this.store.focusedNode.id ? '#fff' : (this.store.theme === 'light' ? '#333' : '#fff')
      )
  }
  
  // 生成子节点
  async explodeNode(parent) {
    if (!parent) {
      console.warn('警告：节点不存在');
      return;
    }

    this.store.focusedNode = parent;
    parent.loading = true;
    this.emit('update');

    parent.fx = parent.x;
    parent.fy = parent.y;

    if (parent.colorGroup === undefined) {
      parent.colorGroup = this.colorGroupCounter++;
    }
    
    let prompt = '';
    if (parent.index > 0 && parent?.label) {
      prompt = `请基于"${parent.label}"，给我衍生出10个词汇，`;
    } else {
      prompt = '请给我随机10个词汇，';
    }
    prompt += '使用中文逗号“，”分割，词汇使用中文。不要多余的话，不要序号，不要空格，只给我词汇即可，格式如：“词汇1，词汇2，词汇3”';
    
    return new Promise(resolve => {
      aiw.bridge.send('agent.generate', {
        prompt: prompt,
        stream: false
      });
      
      aiw.bridge.once('agent.generate', ({ status, data, message }) => {
        if (status === 'SUCCEEDED') {
          const list = data.split('，');
          const newNodes = list.map((item, i) => ({
            id: `${parent.id}-${Date.now()}-${i}`,
            label: item,
            exploded: false,
            loading: false,
            cluster: parent.cluster,
            colorGroup: parent.colorGroup,
            children: [],
            x: parent.x,
            y: parent.y,
            parentId: parent.id
          }));

          const radius = CONFIG.NODE_RADIUS * (parent.children.length + 1) * 8;
          newNodes.forEach((node, i) => {
            const angle = (i / list.length) * 2 * Math.PI;
            node.x = parent.x + radius * Math.cos(angle);
            node.y = parent.y + radius * Math.sin(angle);
          });

          if (!Array.isArray(parent.children)) {
            parent.children = [];
          }
          parent.children.push(...newNodes);

          parent.loading = false;

          setTimeout(() => {
            parent.fx = null;
            parent.fy = null;
            resolve();
          }, CONFIG.NODE_LOCK_DURATION);

          this.emit('update');
        } else if (status === '[END]' || status === 'ERROR') {
          parent.loading = false;
          this.emit('update');
          resolve();
        }
      })
    });
  }
  
  // 分配新的颜色组
  assignNewColorGroup(node) {
    node.colorGroup = this.colorGroupCounter++

    if (node.children) {
      node.children.forEach(child => {
        child.colorGroup = node.colorGroup
        this.assignNewColorGroup(child)
      })
    }
  }
  
  // 更新图表
  update() {
    if (!this.svgElement) return

    const svg = d3.select(this.svgElement)
    const { nodes, links } = this.flattenTree(this.root)

    if (!this.gContent) {
      this.gContent = svg.append('g').attr('class', 'content')
      this.gLinks = this.gContent.append('g').attr('class', 'links')
      this.gNodes = this.gContent.append('g').attr('class', 'nodes')

      if (this.zoom && this.transformState) {
        svg.call(this.zoom).call(this.zoom.transform, this.transformState)
      }
    }

    if (!this.simulation) {
      this.initializeSimulation(nodes, links)
    } else {
      this.simulation.nodes(nodes)
      this.simulation.force('link').links(links)
      this.simulation.force('charge').strength(-300)
      this.simulation.alpha(1).restart()
    }

    // 更新连接线
    this.linkEls = this.gLinks.selectAll('line')
      .data(links, d => `${d.source.id}-${d.target.id}`)
      .join(
        enter => enter.append('line')
          .attr('stroke', d => this.colorScale(d.source.colorGroup))
          .attr('stroke-width', 1)
          .attr('opacity', 0)
          .transition()
          .duration(CONFIG.TRANSITION_DURATION)
          .attr('opacity', 0.6),
        update => update
          .attr('stroke', d => this.colorScale(d.source.colorGroup)),
        exit => exit.transition()
          .duration(CONFIG.TRANSITION_DURATION)
          .attr('opacity', 0)
          .remove()
      )

    // 更新节点
    this.nodeEls = this.gNodes.selectAll('g.node')
      .data(nodes, d => d.id)
      .join(
        enter => {
          const nodeGroup = enter.append('g')
            .attr('class', 'node')
            .attr('transform', d => `translate(${d.x ?? this.state.width / 2},${d.y ?? this.state.height / 2})`)
            .attr('opacity', 0)

          // 节点圆形
          const circle = nodeGroup.append('circle')
            .attr('r', 0)
            .attr('fill', d => this.colorScale(d.colorGroup))
            .attr('stroke', this.store.theme === 'light' ? '#333' : '#fff')
            .attr('stroke-width', 1.5)
            .style('cursor', 'pointer')
            .on('click', async (e, d) => {
              if (d.loading) return
              this.assignNewColorGroup(d)
              await this.explodeNode(d)
            })
            .on('contextmenu', (e, d) => {
              e.preventDefault()
              this.emit('contextmenu', e, d)
            })
            .on('mouseover', (e, d) => {
              d3.select(e.currentTarget)
                .transition()
                .duration(200)
                .attr('r', CONFIG.NODE_RADIUS * 1.2)
                .attr('stroke-width', d.id === this.store.focusedNode?.id ? 3 : 2)
            })
            .on('mouseout', (e, d) => {
              d3.select(e.currentTarget)
                .transition()
                .duration(200)
                .attr('r', CONFIG.NODE_RADIUS)
                .attr('stroke-width', d.id === this.store.focusedNode?.id ? 3 : 1.5)
            })

          // 节点标签
          nodeGroup.append('text')
            .text(d => d.label)
            .attr('x', 24)
            .attr('y', 4)
            .attr('fill', this.store.theme === 'light' ? '#333' : '#fff')
            .attr('font-size', 12)
            .attr('pointer-events', 'none')
            .style('user-select', 'none')
            .attr('opacity', 0)

          // 加载指示器
          const loadingGroup = nodeGroup.append('g')
            .attr('class', 'loading-indicator')
            .style('display', 'none')

          // 脉冲环
          loadingGroup.append('circle')
            .attr('r', CONFIG.NODE_RADIUS)
            .attr('fill', 'none')
            .attr('stroke', '#fff')
            .attr('stroke-width', 2)

          // 旋转环
          loadingGroup.append('circle')
            .attr('r', CONFIG.NODE_RADIUS - 4)
            .attr('fill', 'none')
            .attr('stroke', '#fff')
            .attr('stroke-width', 2)
            .attr('stroke-dasharray', '25, 10')

          // 中心圆点
          loadingGroup.append('circle')
            .attr('r', 3)
            .attr('fill', '#fff')

          // 进入动画
          nodeGroup.transition()
            .duration(CONFIG.TRANSITION_DURATION)
            .attr('opacity', 1)

          circle.transition()
            .duration(CONFIG.TRANSITION_DURATION)
            .attr('r', CONFIG.NODE_RADIUS)
            .attr('fill', d => this.colorScale(d.colorGroup))

          nodeGroup.select('text')
            .transition()
            .duration(CONFIG.TRANSITION_DURATION)
            .attr('opacity', 1)

          return nodeGroup
        },
        update => update,
        exit => exit.transition()
          .duration(CONFIG.TRANSITION_DURATION)
          .attr('opacity', 0)
          .remove()
      )

    // 更新加载状态
    const loadingIndicators = this.nodeEls.select('.loading-indicator')
      .style('display', d => d.loading ? 'block' : 'none')

    // 启动加载动画
    loadingIndicators.each(function () {
      const group = d3.select(this)
      if (group.style('display') !== 'none') {
        const pulseRing = group.select('circle:nth-child(1)')
        if (!pulseRing.attr('data-animating')) {
          pulseRing.attr('data-animating', 'true')
          
          // 脉冲动画
          function animatePulse() {
            pulseRing.transition()
              .duration(2000)
              .attr('r', CONFIG.NODE_RADIUS * 2)
              .attr('opacity', 0)
              .on('end', () => {
                pulseRing.attr('r', CONFIG.NODE_RADIUS).attr('opacity', 1)
                animatePulse()
              })
          }
          
          // 旋转动画
          function animateSpin() {
            group.select('circle:nth-child(2)').transition()
              .duration(2000)
              .attrTween('transform', () => d3.interpolateString('rotate(0)', 'rotate(360)'))
              .on('end', animateSpin)
          }
          
          // 圆点脉动动画
          function animateDot() {
            group.select('circle:nth-child(3)').transition()
              .duration(1500)
              .attr('r', 5)
              .attr('opacity', 0.7)
              .transition()
              .duration(1500)
              .attr('r', 3)
              .attr('opacity', 1)
              .on('end', animateDot)
          }
          
          animatePulse()
          animateSpin()
          animateDot()
        }
      }
    })

    // 高亮聚焦的节点
    this.highlightFocusedNode()

    // 启用拖拽
    this.enableDrag(this.nodeEls)
  }
  
  // 缩放操作
  zoomIn() {
    if (!this.svgElement || !this.zoom) return
    d3.select(this.svgElement).transition()
      .duration(500)
      .call(this.zoom.scaleBy, 1.2)
  }
  
  zoomOut() {
    if (!this.svgElement || !this.zoom) return
    d3.select(this.svgElement).transition()
      .duration(500)
      .call(this.zoom.scaleBy, 0.8)
  }
  
  // 移动到视图中心
  moveToViewCenter() {
    if (!this.svgElement || !this.root || !this.transformState) return;

    const svg = d3.select(this.svgElement);
    const currentTransform = this.transformState;
    const targetX = this.state.width / 2;
    const targetY = this.state.height / 2;
    
    const viewRootX = this.root.x * currentTransform.k + currentTransform.x;
    const viewRootY = this.root.y * currentTransform.k + currentTransform.y;
    
    const dx = targetX - viewRootX;
    const dy = targetY - viewRootY;
    
    const targetTransform = currentTransform.translate(dx, dy);
    
    svg.transition()
      .duration(500)
      .call(this.zoom.transform, targetTransform);
  }
  
  // 移动指定节点到中心
  moveNodeToViewCenter(node) {
    if (!this.svgElement || !node || !this.transformState) return;

    const svg = d3.select(this.svgElement);
    const currentTransform = this.transformState;
    const viewWidth = this.state.width;
    const viewHeight = this.state.height;

    const targetViewX = viewWidth / 2;
    const targetViewY = viewHeight / 2;

    const currentViewX = node.x * currentTransform.k + currentTransform.x;
    const currentViewY = node.y * currentTransform.k + currentTransform.y;

    const dx = targetViewX - currentViewX;
    const dy = targetViewY - currentViewY;

    svg.transition()
      .duration(500)
      .call(this.zoom.transform, currentTransform.translate(dx, dy));
  }
  
  // 重置图表
  reset() {
    this.store.focusedNode = null
    this.clusterCounter = 0
    this.colorGroupCounter = 0
    this.root = this.createRootNode()
    this.root.x = this.state.width / 2
    this.root.y = this.state.height / 2
    this.emit('update')
  }
  
  // 切换主题
  toggleTheme() {
    this.store.theme = this.store.theme === 'dark' ? 'light' : 'dark';
    aiw.toggleTheme(this.store.theme);
    this.emit('theme-change', this.store.theme);
  }
  
  // 删除节点
  deleteNode(nodeToDelete) {
    // 根节点不能删除
    if (nodeToDelete.id === '0') return;
    
    // 递归查找并删除节点
    const removeNode = (parent, targetId) => {
      if (!parent || !parent.children) return false;
      
      for (let i = 0; i < parent.children.length; i++) {
        if (parent.children[i].id === targetId) {
          parent.children.splice(i, 1);
          return true;
        }
        
        if (removeNode(parent.children[i], targetId)) {
          return true;
        }
      }
      
      return false;
    };
    
    removeNode(this.root, nodeToDelete.id);
    
    // 如果删除的是当前聚焦节点，则取消聚焦
    if (this.store.focusedNode && this.store.focusedNode.id === nodeToDelete.id) {
      this.store.focusedNode = null;
    }
    
    this.emit('update');
  }
  
  // 事件系统
  on(event, callback) {
    if (!this.eventListeners[event]) {
      this.eventListeners[event] = [];
    }
    this.eventListeners[event].push(callback);
  }
  
  emit(event, ...args) {
    if (this.eventListeners[event]) {
      this.eventListeners[event].forEach(callback => callback(...args));
    }
  }
  
  // 调整大小
  resize(width, height) {
    this.state.width = width;
    this.state.height = height;
    this.root.x = width / 2;
    this.root.y = height / 2;
    this.emit('update');
  }
}

export default new GalaxyCore();